package cond

import (
	cond "clientDemo/service/cond"
	"clientDemo/service/modulemgr"
	"clientDemo/utils"
	"strings"
)

var _m *CondModule

const (
	GroWth_ID1 = 80001
	GroWth_ID2 = 80002
	GroWth_ID3 = 80003

	Chat_Channel_ID1 = 50001 //聊天频道1
	Chat_Channel_ID2 = 50002 //聊天频道2
	Chat_Channel_ID3 = 50003 //聊天频道3
	Chat_Channel_ID4 = 50004 //聊天频道4
)

// 条件归纳
type CondCollectData struct {
	RootCategoryId uint32
	DataSourceFn   cond.DataSourceFunction
	//Data           map[uint32]*CondCollectDataItem
}

//	type CondCollectDataItem struct {
//		ItemData map[string]*CollectData
//	}
//
//	type CollectData struct {
//		Id   uint32
//		conf *ConditionConfig
//	}
type CondRoleItem struct {
	Id           uint32
	conf         *cond.ConditionConfig
	OperateScore int64 //操作后的值
	TimeCount    int64 //计数
	categoryId   uint32
	//Type      uint32
	//CountType Match_Type
}

func (c *CondRoleItem) Conf() *cond.ConditionConfig {
	return c.conf
}
func (c *CondRoleItem) GetId() uint32 {
	return c.Id
}
func (c *CondRoleItem) GetOperateScore() int64 {
	return c.OperateScore
}
func (c *CondRoleItem) SetOperateScore(op int64) {
	c.OperateScore = op
}
func (c *CondRoleItem) AddTimeCount() {
	c.TimeCount++
}
func (c *CondRoleItem) GetTimeCount() int64 {
	return c.TimeCount
}

type AllCondItem struct {
	AllCondMap   map[uint32]*CondRoleItem   // 所有的条件数据（和表格相关）
	IndexCondMap map[uint32][]*CondRoleItem // 索引结构 catogoryId --> condIds
}
type CondModule struct {
	globalCondMap map[uint32]*CondRoleItem //condId --> 条件数据

	condMap       map[uint32]*AllCondItem     //roleId --> condId --> 条件数据
	CondConfigMap map[uint32]*CondCollectData //条件数据抽象内核

	// 数据源函数
	datasourceMap       map[uint32]cond.DataSourceFunction
	datasourceUpdateMap map[uint32]cond.DataSourceUpdateFunction

	// 操作器,统计数值用
	operateMap map[cond.Operate_Type]cond.DataOperateFunction

	// 比较器
	comparerMap map[cond.Comparer_Type]cond.DataComparerFunction

	// 条件触发成功回调
	bindCondCbMap map[uint32][]*WatchDataInfo //catogoryId --> watchData数组-->moduleName数组

	// 假数据集合
	growthData   map[uint32]*GrowthAllData
	chatData     map[uint32]*ChatAllData
	variableData map[uint32]*VariableAllData
	openDayData  uint32
}

func NewCondModule() *CondModule {
	tmp := &CondModule{
		globalCondMap: make(map[uint32]*CondRoleItem),

		condMap: make(map[uint32]*AllCondItem),
		//CondConfigMap: make(map[uint32]*CondCollectData),
		datasourceMap: make(map[uint32]cond.DataSourceFunction),

		// 操作器
		operateMap: make(map[cond.Operate_Type]cond.DataOperateFunction),
		// 比较器
		comparerMap: make(map[cond.Comparer_Type]cond.DataComparerFunction),

		growthData:   make(map[uint32]*GrowthAllData),
		chatData:     make(map[uint32]*ChatAllData),
		variableData: make(map[uint32]*VariableAllData),

		bindCondCbMap: make(map[uint32][]*WatchDataInfo),
	}
	return tmp
}
func (m *CondModule) Init(mm modulemgr.IModuleManager) (bool, error) {
	_m = m
	m.initComparer()
	m.initOperate()
	var condList []cond.ConditionConfig = []cond.ConditionConfig{
		{Id: 1000, Name: "养成线1", Operate: Cond_Operate_GetValue, CompareType: Comparer_Type_Equal, MatchType: cond.Cond_Match_Inherent, ValueParamType: cond.Cond_ValueParamType_Growth_Level, MatchParam: [][]string{{"100|80001"}}},
		{Id: 1001, Name: "养成线2", Operate: Cond_Operate_GetValue, CompareType: Comparer_Type_Equal, MatchType: cond.Cond_Match_Inherent, ValueParamType: cond.Cond_ValueParamType_Growth_Level, MatchParam: [][]string{{"100|80002"}}},
		{Id: 1002, Name: "天数", Operate: Cond_Operate_GetValue, CompareType: Comparer_Type_Equal, MatchType: cond.Cond_Match_Inherent, ValueParamType: cond.Cond_ValueParamType_OpenDay, MatchParam: [][]string{{"104|1002"}}},
		{Id: 1003, Name: "聊天", Operate: Cond_Operate_GetValue, CompareType: Comparer_Type_Equal, MatchType: cond.Cond_Match_Inherent, ValueParamType: cond.Cond_ValueParamType_Chat_Num, MatchParam: [][]string{{"101|50001"}}},
		{Id: 1004, Name: "变量", Operate: Cond_Operate_GetValue, CompareType: Comparer_Type_Equal, MatchType: cond.Cond_Match_Inherent, ValueParamType: cond.Cond_ValueParamType_Variable, MatchParam: [][]string{{"102|1001"}}},
	}
	// 数据源获取
	//m.RegeditDataSource(cond.Value_Category_Growth, m.GetRoleGrowthData)
	m.RegeditDataSource(cond.Value_Category_Chat, m.GetRoleGrowthData)
	m.RegeditDataSource(cond.Value_Category_Variable, m.GetRoleVariableData)
	m.RegeditDataSource(cond.Value_Category_Global, m.GetRoleGlobalData)
	for j := 0; j < len(condList); j++ {
		config := condList[j]
		arr := strings.Split(config.MatchParam[0][0], "|")
		rootCategoryId := utils.ParseUint32(arr[0])
		o := &CondRoleItem{
			Id:           config.Id,
			OperateScore: 0,
			conf:         &config,
			categoryId:   rootCategoryId,
		}
		m.globalCondMap[config.Id] = o
	}

	/*	for i := 0; i < len(condList); i++ {
		conf := condList[i]
		if len(conf.MatchParam) == 0 || len(conf.MatchParam[0]) == 0 {
			continue
		}
		arr := strings.Split(conf.MatchParam[0][0], "|")
		rootCategoryId := utils.ParseUint32(arr[0])
		sourceFun := m.datasourceMap[rootCategoryId]
		if sourceFun == nil {
			panic("cond: no datasource function")
		}
		data, ok := m.CondConfigMap[rootCategoryId]
		if !ok {
			data = &CondCollectData{
				RootCategoryId: rootCategoryId,
				DataSourceFn:   sourceFun,
			}
		}
		_ = data
	}*/
	// 构建十个玩家的基本条件数据
	for i := uint32(0); i < 10; i++ {
		obj := &AllCondItem{
			AllCondMap:   map[uint32]*CondRoleItem{},
			IndexCondMap: map[uint32][]*CondRoleItem{},
		}
		var All = obj.AllCondMap
		for j := 0; j < len(condList); j++ {
			config := condList[j]
			arr := strings.Split(config.MatchParam[0][0], "|")
			rootCategoryId := utils.ParseUint32(arr[0])
			o := &CondRoleItem{
				Id:           config.Id,
				OperateScore: 0,
				conf:         &config,
				categoryId:   rootCategoryId,
			}
			All[config.Id] = o

			indexList, ok := obj.IndexCondMap[rootCategoryId]
			if !ok {
				indexList = make([]*CondRoleItem, 0)
			}
			indexList = append(indexList, o)
			obj.IndexCondMap[rootCategoryId] = indexList
		}
		m.condMap[i] = obj
	}
	return true, nil
}

func (m *CondModule) Run(mm modulemgr.IModuleManager) (bool, error) {
	return false, nil
}

func (m *CondModule) RegeditBindCond(moduleName string, express string, cb cond.CondWatchEventCb) {
	arr := strings.Split(express, ":")
	if len(arr) < 2 {
		return
	}
	condId := utils.ParseUint32(arr[0])
	conf, ok := m.globalCondMap[condId]
	if !ok {
		return
	}

	data, ok := m.bindCondCbMap[utils.ParseUint32(arr[0])]
	if !ok {
		o := &WatchDataInfo{
			RootCategoryId: conf.categoryId,
			targetScore:    utils.ParseInt64(arr[1]),
			WatchList: &WatchDataItem{
				moduleName:   moduleName,
				WatchEventCb: cb,
			},
		}
		m.bindCondCbMap[utils.ParseUint32(arr[0])] = []*WatchDataInfo{o}
	}
	data = append(data, &WatchDataInfo{
		RootCategoryId: conf.categoryId,
		targetScore:    utils.ParseInt64(arr[1]),
		WatchList: &WatchDataItem{
			moduleName:   moduleName,
			WatchEventCb: cb,
		},
	})
	m.bindCondCbMap[utils.ParseUint32(arr[0])] = data
}

// DispatchDataSource 找到大分类的所有cond, 【匹配cond】, cond关联的表达式, 匹配表达式下其他条件，【匹配表达式】 遍历回调表达式下面的所有callback
func (m *CondModule) DispatchDataSource(roleId uint32, categoryId uint32, param []interface{}, count uint64) {
	roleData, ok := m.condMap[roleId]
	if !ok || roleData == nil {
		return
	}
	condList, ok := roleData.IndexCondMap[categoryId]
	if !ok || condList == nil {
		return
	}
	for i := 0; i < len(condList); i++ {
		o := condList[i]
		ok := m.matchCondType(o.conf, param)
		if !ok {
			continue
		}
		sourceDataCb, ok := m.datasourceMap[categoryId]
		if !ok {
			continue
		}
		watchInfo, ok := m.bindCondCbMap[o.Id]
		if !ok {
			continue
		}
		id := param[0].(uint32)
		queryType := param[1].(uint32)
		var param2 = []interface{}{id, queryType}
		score := sourceDataCb(roleId, param2)
		for _, item := range watchInfo {
			ok = m.matchCond(o, item, score)
			if !ok {
				continue
			}
			item.WatchList.WatchEventCb(roleId, o.conf, score)
		}
	}
	/*for _, v := range roleData.IndexCondMap {
		for i := 0; i < len(v); i++ {
			o := v[i]
			if o == nil {
				continue
			}
			if o.categoryId != categoryId {
				continue
			}
			ok := m.matchCondType(o.conf, param)
			if ok {
				continue
			}
			sourceDataCb, ok := m.datasourceMap[categoryId]
			if !ok {
				continue
			}
			watchInfo, ok := m.bindCondCbMap[categoryId]
			if !ok {
				continue
			}
			var param2 []interface{}
			score := sourceDataCb(roleId, param2)
			for _, item := range watchInfo.WatchList {
				item.WatchEventCb(roleId, o.conf, score)
			}
			//if o.conf.MatchType == Cond_MatchType_Inherent {
			//	v.OperateScore += int64(count)
			//} else if v.CountType == Cond_MatchType_Count {
			//	v.OperateScore += int64(1)
			//}
			//confData, ok := m.CondConfigMap[v.Id]
			//if ok {
			//	if v.OperateScore >= confData.TargetScore { //触发条件
			//		confData.EventCb(v.Id, roleId, v.OperateScore)
			//	}
			//}
		}
	}*/
}
func (m *CondModule) matchCond(condData cond.ICondRoleItem, watchInfo *WatchDataInfo, score int64) bool {
	if condData.Conf() == nil || condData.Conf().CompareType == 0 {
		return false
	}
	fn, ok := m.comparerMap[condData.Conf().CompareType]
	if !ok {
		return false
	}

	fnOp, ok := m.operateMap[condData.Conf().Operate]
	if !ok {
		return false
	}
	_score := fnOp(condData, score)
	return fn(_score, watchInfo.targetScore)
}

// matchCondType 触发的数据是否匹配
func (m *CondModule) matchCondType(conf *cond.ConditionConfig, param []interface{}) bool {
	if len(param) == 0 {
		return false
	}
	subCategoryId := param[1].(uint32)
	if conf.ValueParamType == cond.ValueParam_Type(subCategoryId) {
		return true
	}
	return false
}
func (m *CondModule) getCondCategoryId(config *cond.ConditionConfig) uint32 {
	arr := strings.Split(config.MatchParam[0][0], "|")
	if len(arr) < 1 {
		return 0
	}
	rootCategoryId := utils.ParseUint32(arr[0])
	return rootCategoryId
}
